package com.coffee.netty.connection;

import com.coffee.netty.CommandHandler;
import com.coffee.netty.util.RemotingUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.Optional;

/**
 * client connect server info
 * @author songkui
 * @since 2024/7/31
 */
@ChannelHandler.Sharable
public class ConnectionRemotingHandler extends SimpleChannelInboundHandler {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(ConnectionRemotingHandler.class);

    private final ConnectionFactory connectionFactory;
    private final ReconnectionHandler reconnectionHandler;
    private final CommandHandler commandHandler;
    public ConnectionRemotingHandler(CommandHandler commandHandler, ReconnectionHandler reconnectionHandler, ConnectionFactory connectionFactory) {
        this.commandHandler = commandHandler;
        this.reconnectionHandler = reconnectionHandler;
        this.connectionFactory = connectionFactory;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        commandHandler.handleCommand(ctx, msg);
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("Connection channel active: {}", RemotingUtil.parseRemoteAddress(ctx.channel()));
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("Connection channel inactive: {}", RemotingUtil.parseRemoteAddress(ctx.channel()));
        super.channelInactive(ctx);

        Connection connection = Connection.getByChannel(ctx.channel());
        Optional.ofNullable(connection).ifPresent(c -> {
            c.setConnectionType(ConnectionType.DisconnectReconnect);
            if (!OnlineType.OffLine.equals(connection.getOnlineType())){
                connection.setOnlineType(OnlineType.Disconnect);
            }
        });

        if (null != connection && connection.isReconnect() && !OnlineType.OffLine.equals(connection.getOnlineType())){
            reconnectionHandler.disconnectReconnect(connectionFactory, connection);  //disconnect Reconnect
        }else {
            commandHandler.channelInactive(ctx);
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
        logger.error("ExceptionCaught in connection: {}, close the connection! Cause[{}:{}]",
                ctx.channel().toString(), throwable.getClass().getSimpleName(), throwable.getMessage());
        logger.error("ExceptionCaught in connection: "+ctx.channel().toString(), throwable);
        ctx.channel().close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }


}
